package cn.zifangsky.license;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.DateFormat;
import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.prefs.Preferences;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.keyware.kd.task.util.SpringContextUtil;
import com.keyware.utils.AESUtils;

import cn.zifangsky.repository.entity.License;
import cn.zifangsky.service.impl.LicenseServiceImpl;
import de.schlichtherle.license.CipherParam;
import de.schlichtherle.license.DefaultCipherParam;
import de.schlichtherle.license.DefaultLicenseParam;
import de.schlichtherle.license.KeyStoreParam;
import de.schlichtherle.license.LicenseContent;
import de.schlichtherle.license.LicenseManager;
import de.schlichtherle.license.LicenseParam;

/**
 * License校验类
 *
 * @author zifangsky
 * @date 2018/4/20
 * @since 1.0.0
 */
public class LicenseVerify {
    public static Logger logger = LoggerFactory.getLogger(LicenseVerify.class);
	private final String webRootPath = LicenseCheckListener.getWebRootAbsolutePath().substring(1, LicenseCheckListener.getWebRootAbsolutePath().length() - 1);


    /**
     * 安装License证书
     * @author zifangsky
     * @date 2018/4/20 16:26
     * @since 1.0.0
     */
    public synchronized LicenseContent install(LicenseVerifyParam param){
        LicenseContent result = null;
        DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String scriptPath =File.separator+ webRootPath + File.separator;
        //1. 安装证书
        try{
            LicenseManager licenseManager = LicenseManagerHolder.getInstance(initLicenseParam(param));
            licenseManager.uninstall();
            
            LicenseServiceImpl licenseService = SpringContextUtil.getBean(LicenseServiceImpl.class);
            License lic=new License();
            License one = licenseService.getOne(AESUtils.encrypt("1","3532263592381276"));
            if(one!=null) {
            	byte[] licenseContext = one.getLicenseContext();
            	fileToBytes(licenseContext,scriptPath,"license.lic");
            }
            result = licenseManager.install(new File(scriptPath+"license.lic"));
            LicenseCheckModel expectedCheckModel = (LicenseCheckModel) result.getExtra();

            logger.info(MessageFormat.format("证书安装成功，证书有效期：{0}",expectedCheckModel.getDay()));
        }catch (Exception e){
            logger.error("证书安装失败！",e);
        }

        return result;
    }

    
    /**
     * 将Byte数组转换成文件
     * @param bytes byte数组
     * @param filePath 文件路径  如 D://test/ 最后“/”结尾
     * @param fileName  文件名
     */
    public static void fileToBytes(byte[] bytes, String filePath, String fileName) {
        BufferedOutputStream bos = null;
        FileOutputStream fos = null;
        File file = null;
        try {

            file = new File(filePath + fileName);
            if (!file.getParentFile().exists()){
                //文件夹不存在 生成
                file.getParentFile().mkdirs();
            }
            fos = new FileOutputStream(file);
            bos = new BufferedOutputStream(fos);
            bos.write(bytes);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (bos != null) {
                try {
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    /**
     * 校验License证书
     * @author zifangsky
     * @date 2018/4/20 16:26
     * @since 1.0.0
     * @return boolean
     */
    public boolean verify(){
        LicenseManager licenseManager = LicenseManagerHolder.getInstance(null);
        DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        boolean falg=false;
        StringBuffer sb = new StringBuffer("3532263592381276");
        //2. 校验证书
        try {
            LicenseContent licenseContent = licenseManager.verify();
            LicenseCheckModel expectedCheckModel = (LicenseCheckModel) licenseContent.getExtra();
            LicenseServiceImpl licenseService = SpringContextUtil.getBean(LicenseServiceImpl.class);
            License one = licenseService.getOne(AESUtils.encrypt("1",sb.toString()));
            if(one!=null) {
            	String encrypt = AESUtils.encrypt(AESUtils.identityToString(one),sb.toString());
            	if(one.getDataContext().equals(encrypt)) {
            		long createDate =Long.parseLong(AESUtils.decrypt(one.getCreateDate(), sb.toString()));//获取证书上传时间
                	long syDate =Long.parseLong(AESUtils.decrypt(one.getSyDate(),sb.toString()));//获取证书使用时间
                	String day = expectedCheckModel.getDay();//获取证书有效天数
                	long dayL=Long.parseLong(day)*24*3600*1000;
                	long betweenDays =syDate-createDate; //求使用了多久  毫秒数
                	if(dayL!=0&&0<=betweenDays&&betweenDays<=dayL) {
                		falg=true;
                        logger.info(MessageFormat.format("证书校验通过，证书有效期：{0}",expectedCheckModel.getDay()));
                	}
            	}
            }else {
            	falg=false;
            }
            return falg;
        }catch (Exception e){
            logger.error("证书校验失败！",e);
            return false;
        }
    }

    /**
     * 初始化证书生成参数
     * @author zifangsky
     * @date 2018/4/20 10:56
     * @since 1.0.0
     * @param param License校验类需要的参数
     * @return de.schlichtherle.license.LicenseParam
     */
    public LicenseParam initLicenseParam(LicenseVerifyParam param){
        Preferences preferences = Preferences.userNodeForPackage(LicenseVerify.class);

        CipherParam cipherParam = new DefaultCipherParam(param.getStorePass());

        KeyStoreParam publicStoreParam = new CustomKeyStoreParam(LicenseVerify.class
                ,param.getPublicKeysStorePath()
                ,param.getPublicAlias()
                ,param.getStorePass()
                ,null);

        return new DefaultLicenseParam(param.getSubject()
                ,preferences
                ,publicStoreParam
                ,cipherParam);
    }
    
    

}
